#ifndef _Ring_QUEUE_HPP_
#define _Ring_QUEUE_HPP_

#include <iostream>
#include <pthread.h>
#include <vector>
#include "sem.hpp"
#include <unistd.h>
#include <cstdlib>

const int g_default_num = 5;

template<class T>
class RingQueue
{
public:
    RingQueue(int default_num = g_default_num)
        :ring_queue_(default_num)
        ,num_(default_num)
        ,c_step(0)
        ,p_step(0)
        ,space_sem_(default_num)
        ,data_sem_(0)
    {
        pthread_mutex_init(&clock, nullptr);
        pthread_mutex_init(&plock, nullptr);
    }
    ~RingQueue()
    {
        pthread_mutex_destroy(&clock);
        pthread_mutex_destroy(&plock);
    }
    //生产者 : 空间资源
    void push(const T& in)
    {
        space_sem_.p();
        pthread_mutex_lock(&plock);
        // 一定是竞争成功的生产者 -- 就一个
        ring_queue_[p_step++] = in;
        p_step %= num_;
        pthread_mutex_unlock(&plock);
        data_sem_.v();
    }
    //消费者 : 数据资源
    void pop(T* out)
    {
        data_sem_.p();
        pthread_mutex_lock(&clock);
        // 一定是竞争成功的消费者 -- 就一个
        *out = ring_queue_[c_step++];
        c_step %= num_;
        pthread_mutex_unlock(&clock);
        space_sem_.v();
    }
    void debug()
    {
        std::cout << "size : " << ring_queue_.size() << " num : " << num_ << std::endl;
    }
private:
    std::vector<T> ring_queue_;
    int num_;
    int c_step;// 消费下标
    int p_step;// 生产下标
    Sem space_sem_;
    Sem data_sem_;
    pthread_mutex_t clock;
    pthread_mutex_t plock;
};

#endif